const WebSocket = require('ws');

// 创建WebSocket服务器
const wss = new WebSocket.Server({ 
  port: 8082,
  host: '0.0.0.0', // 监听所有网络接口
  path: '/ws' // 指定WebSocket路径
});

console.log('WebSocket服务器启动在端口 8082');

// 存储连接的客户端
const clients = new Map();
const rooms = new Map();

// 处理连接
wss.on('connection', (ws, req) => {
  const clientId = Date.now().toString();
  const client = {
    id: clientId,
    ws: ws,
    userId: null,
    nickname: null,
    currentRoom: null
  };
  
  clients.set(clientId, client);
  
  console.log(`客户端 ${clientId} 已连接`);
  
  // 发送连接确认
  sendToClient(ws, {
    type: 'connection',
    message: '连接成功',
    clientId: clientId
  });

  // 处理消息
  ws.on('message', (data) => {
    try {
      const message = JSON.parse(data);
      console.log('收到消息:', message);
      
      handleMessage(client, message);
    } catch (error) {
      console.error('解析消息失败:', error);
      sendToClient(ws, {
        type: 'error',
        message: '消息格式错误'
      });
    }
  });

  // 处理断开连接
  ws.on('close', () => {
    console.log(`客户端 ${clientId} 已断开连接`);
    
    // 离开房间
    if (client.currentRoom) {
      leaveRoom(client, client.currentRoom);
    }
    
    clients.delete(clientId);
  });

  // 处理错误
  ws.on('error', (error) => {
    console.error(`客户端 ${clientId} 错误:`, error);
  });
});

// 处理消息
function handleMessage(client, message) {
  const { type, data } = message;
  
  switch (type) {
    case 'heartbeat':
      handleHeartbeat(client, data);
      break;
    case 'login':
      handleLogin(client, data);
      break;
    case 'room_enter':
      handleRoomEnter(client, data);
      break;
    case 'room_exit':
      handleRoomExit(client, data);
      break;
    case 'cube_move':
      handleCubeMove(client, data);
      break;
    case 'cube_angle':
      handleCubeAngle(client, data);
      break;
    case 'cube_state':
      handleCubeState(client, data);
      break;
    case 'round_progress':
      handleRoundProgress(client, data);
      break;
    case 'player_status_update':
      handlePlayerStatusUpdate(client, data);
      break;
    case 'game_observer':
      handleGameObserver(client, data);
      break;
    default:
      console.log('未知消息类型:', type);
  }
}

// 处理登录
function handleLogin(client, data) {
  const { token } = data;
  
  console.log(`客户端 ${client.id} 登录，token: ${token}`);
  
  // 模拟登录验证
  client.userId = `user_${Date.now()}`;
  
  sendToClient(client.ws, {
    type: 'login_response',
    code: 1,
    message: '登录成功',
    userId: client.userId
  });
}

// 处理心跳
function handleHeartbeat(client, data) {
  sendToClient(client.ws, {
    type: 'heartbeat_response',
    timestamp: Date.now(),
    data: data
  });
}

// 处理进入房间
function handleRoomEnter(client, data) {
  const { roomId, nickName } = data;
  
  // 离开当前房间
  if (client.currentRoom) {
    leaveRoom(client, client.currentRoom);
  }
  
  // 加入新房间
  if (!rooms.has(roomId)) {
    rooms.set(roomId, new Set());
  }
  
  const room = rooms.get(roomId);
  room.add(client.id);
  
  client.currentRoom = roomId;
  client.nickname = nickName;
  
  console.log(`客户端 ${client.id} 加入房间 ${roomId}`);
  
  // 发送确认消息
  sendToClient(client.ws, {
    type: 'room_enter_response',
    roomId: roomId,
    success: true,
    message: '成功加入房间'
  });
  
  // 广播给房间内其他用户
  broadcastToRoom(roomId, {
    type: 'userJoined',
    roomId: roomId,
    userId: client.id,
    nickname: nickName,
    timestamp: Date.now()
  }, client.id);
}

// 处理离开房间
function handleRoomExit(client, data) {
  const { roomId } = data;
  
  if (client.currentRoom === roomId) {
    leaveRoom(client, roomId);
  }
  
  sendToClient(client.ws, {
    type: 'room_exit_response',
    roomId: roomId,
    success: true,
    message: '成功离开房间'
  });
}

// 处理魔方操作
function handleCubeMove(client, data) {
  const { move, interval, step, rotate, modify } = data;
  
  console.log(`客户端 ${client.id} 发送魔方操作: ${move}`);
  
  // 广播给房间内其他用户
  if (client.currentRoom) {
    broadcastToRoom(client.currentRoom, {
      type: 'player_cube_action',
      userId: client.id,
      nickname: client.nickname,
      move: move,
      interval: interval,
      step: step,
      rotate: rotate,
      modify: modify,
      timestamp: Date.now()
    }, client.id);
  }
  
  // 发送确认
  sendToClient(client.ws, {
    type: 'cube_move_response',
    success: true,
    message: '魔方操作已发送'
  });
}

// 处理陀螺仪数据
function handleCubeAngle(client, data) {
  const { x, y, z } = data;
  
  console.log(`客户端 ${client.id} 发送陀螺仪数据: x=${x}, y=${y}, z=${z}`);
  
  // 广播给房间内其他用户
  if (client.currentRoom) {
    broadcastToRoom(client.currentRoom, {
      type: 'cube_angle',
      userId: client.id,
      nickname: client.nickname,
      x: x,
      y: y,
      z: z,
      timestamp: Date.now()
    }, client.id);
  }
}

// 处理魔方状态
function handleCubeState(client, data) {
  const { stateL, upFrontL } = data;
  
  console.log(`客户端 ${client.id} 发送魔方状态`);
  
  // 广播给房间内其他用户
  if (client.currentRoom) {
    broadcastToRoom(client.currentRoom, {
      type: 'cube_state',
      userId: client.id,
      nickname: client.nickname,
      stateL: stateL,
      upFrontL: upFrontL,
      timestamp: Date.now()
    }, client.id);
  }
}

// 处理回合进度
function handleRoundProgress(client, data) {
  const { steps, rotate, tps, smooth, currentTPS, progress } = data;
  
  console.log(`客户端 ${client.id} 发送回合进度: ${progress}%`);
  
  // 广播给房间内其他用户
  if (client.currentRoom) {
    broadcastToRoom(client.currentRoom, {
      type: 'round_progress',
      userId: client.id,
      nickname: client.nickname,
      steps: steps,
      rotate: rotate,
      tps: tps,
      smooth: smooth,
      currentTPS: currentTPS,
      progress: progress,
      timestamp: Date.now()
    }, client.id);
  }
}

// 处理选手状态更新
function handlePlayerStatusUpdate(client, data) {
  const { userId, compId, roomId, action } = data;
  
  console.log(`客户端 ${client.id} 更新选手状态: action=${action}`);
  
  // 广播给房间内其他用户
  if (client.currentRoom) {
    broadcastToRoom(client.currentRoom, {
      type: 'player_status',
      userId: userId,
      compId: compId,
      roomId: roomId,
      action: action,
      timestamp: Date.now()
    }, client.id);
  }
}

// 处理观战请求
function handleGameObserver(client, data) {
  const { followState } = data;
  
  console.log(`客户端 ${client.id} 观战请求: followState=${followState}`);
  
  // 广播给房间内其他用户
  if (client.currentRoom) {
    broadcastToRoom(client.currentRoom, {
      type: 'game_observer',
      userId: client.id,
      nickname: client.nickname,
      followState: followState,
      timestamp: Date.now()
    }, client.id);
  }
}

// 离开房间
function leaveRoom(client, roomId) {
  if (rooms.has(roomId)) {
    const room = rooms.get(roomId);
    room.delete(client.id);
    
    // 如果房间为空，删除房间
    if (room.size === 0) {
      rooms.delete(roomId);
    } else {
      // 广播用户离开消息
      broadcastToRoom(roomId, {
        type: 'userLeft',
        roomId: roomId,
        userId: client.id,
        nickname: client.nickname,
        timestamp: Date.now()
      }, client.id);
    }
  }
  
  client.currentRoom = null;
  console.log(`客户端 ${client.id} 离开房间 ${roomId}`);
}

// 发送消息给客户端
function sendToClient(ws, message) {
  if (ws.readyState === WebSocket.OPEN) {
    ws.send(JSON.stringify(message));
  }
}

// 广播消息给房间内所有用户
function broadcastToRoom(roomId, message, excludeClientId = null) {
  if (rooms.has(roomId)) {
    const room = rooms.get(roomId);
    
    room.forEach(clientId => {
      if (clientId !== excludeClientId) {
        const client = clients.get(clientId);
        if (client && client.ws.readyState === WebSocket.OPEN) {
          client.ws.send(JSON.stringify(message));
        }
      }
    });
  }
}

// 定期清理断开的连接
setInterval(() => {
  clients.forEach((client, clientId) => {
    if (client.ws.readyState === WebSocket.CLOSED) {
      console.log(`清理断开的客户端 ${clientId}`);
      clients.delete(clientId);
      
      if (client.currentRoom) {
        leaveRoom(client, client.currentRoom);
      }
    }
  });
}, 30000); // 每30秒清理一次

console.log('WebSocket服务器模拟器已启动');
console.log('支持的消息类型:');
console.log('- /app/heartbeat: 心跳');
console.log('- /app/roomEnter: 进入房间');
console.log('- /app/roomExit: 离开房间');
console.log('- /app/cubeMove: 魔方操作');
console.log('- /app/subscribe: 订阅房间');
console.log('- /app/unsubscribe: 取消订阅'); 